package com.tansun.ruledata.data.dao;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.xml.transform.stream.StreamSource;

import org.apache.commons.lang3.StringUtils;
import org.dmg.pmml.FieldName;
import org.dmg.pmml.PMML;
import org.jpmml.evaluator.Classification;
import org.jpmml.evaluator.DoubleValue;
import org.jpmml.evaluator.Evaluator;
import org.jpmml.evaluator.FieldValue;
import org.jpmml.evaluator.InputField;
import org.jpmml.evaluator.ModelEvaluatorBuilder;
import org.jpmml.evaluator.Regression;
import org.jpmml.evaluator.TargetField;
import org.jpmml.model.JAXBUtil;

import com.tansun.rule.config.AppConfiguration;
import com.tansun.ruledata.data.entity.DeployReferenceData;

public class DataMiningDao {
	public static void evaluatePmml(String code,String projectCode,Map dataMap) {
		Map<String,Map<String, DeployReferenceData>> proPmmlMap = AppConfiguration.PmmlRefParamMap.get(projectCode);
		if(proPmmlMap==null)
			return;
		Map<String, DeployReferenceData> refParams = proPmmlMap.get(code);
		if(refParams==null)
			return;
		InputStream is = null;
		try {
			Map<String,String> pmmlMap = AppConfiguration.PmmlMap.get(projectCode);
			if(pmmlMap==null)
				return;
			String pmmlStr = pmmlMap.get(code);
			if(StringUtils.isEmpty(pmmlStr))
				return;
			is = new ByteArrayInputStream(pmmlStr.getBytes());
			PMML pmml = JAXBUtil.unmarshalPMML(new StreamSource(is));
			ModelEvaluatorBuilder modelEvaluatorBuilder = new ModelEvaluatorBuilder(pmml);
			Evaluator evaluator = modelEvaluatorBuilder.build();
			//Preparing the argument map:
			Map<FieldName, FieldValue> arguments = new LinkedHashMap();
			List<InputField> inputFields = evaluator.getInputFields();
			for(InputField inputField : inputFields){
				FieldName inputFieldName = inputField.getName();
				// The raw (ie. user-supplied) value could be any Java primitive value
				DeployReferenceData ruleReferenceData = refParams.get(inputFieldName.getValue());
				Map data = (Map) dataMap.get(ruleReferenceData.getClassName());
				Object rawValue = data.get(ruleReferenceData.getNameen());
				// The raw value is passed through: 1) outlier treatment, 2) missing value treatment, 3) invalid value treatment and 4) type conversion
				FieldValue inputFieldValue = inputField.prepare(rawValue);
				arguments.put(inputFieldName, inputFieldValue);
			}
			Map<FieldName, ?> results = evaluator.evaluate(arguments);
			//Extracting secondary results from the result map:
			List<TargetField> targetFields = evaluator.getTargetFields();
			for(TargetField targetField : targetFields){
				FieldName targetFieldName = targetField.getName();
				Object targetFieldValue = null;
				DoubleValue probability = null;
				Object obj = results.get(targetFieldName);
				DeployReferenceData ruleReferenceData = refParams.get(targetFieldName.getValue());
				Map data = (Map) dataMap.get(ruleReferenceData.getClassName());
				/**
				 * ToDo:需要修改，目前针对分类模型，回归模型，可能为全面覆盖到，需要修改
				 */
				//分类模型
				if(obj instanceof Classification){
					Classification node = (Classification)obj;
		        	targetFieldValue = node.getResult();
		        	probability = (DoubleValue)node.getValues().get(targetFieldValue.toString());
					data.put(ruleReferenceData.getNameen()+"_probability", probability.getValue());
		        //回归模型
				}else if(obj instanceof Regression){
					Regression node = (Regression)obj;
		        	targetFieldValue = node.getResult();
				}else{
					targetFieldValue = obj;
				}
				data.put(ruleReferenceData.getNameen(), targetFieldValue);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally{
			if(is!=null)
				try {
					is.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}
	}
}
